package com.cskaoyan.javase._2inner._5anonymous._0introduction;

import com.cskaoyan.javase._1interface._4example.Test;
import com.sun.scenario.effect.impl.sw.sse.SSEBlend_SRC_OUTPeer;

/**
 * 成员内部类,静态内部类,局部内部类,终究是在类中定义了一个类
 * 但是它们的本质仍然是需要一个对象
 * 于是我们一步到位,直接在类中创建内部类对象,这就是匿名内部类以及lambda表达式
 *
 * 匿名内部类,指的是匿名的,特殊的局部内部类
 * 既然这个类是匿名的,那么在定义该匿名类时,如果不直接创建对象使用,那后面就再也用不了了
 * 所以匿名内部类的语法,并不是定义类,而是直接创建对象
 * 匿名内部类,更准确的说明是"匿名内部类对象"
 *
 * 语法:
 * new 类名或者接口名(){
 *   // 某类名或接口名的子类的类体
 * };
 * 解释:
 *      1.匿名内部类终究是一个特殊的局部内部类,它仍然定义在局部位置
 *      2.new关键字仍然表示创建对象
 *      3.语法结构中的"类名或者接口名"部分,可以写普通类,抽象类,也可以写接口
 *      4.匿名内部类语法中,隐含了"继承或者实现"
 *          通过匿名内部类语法创建的是语法结构中"类名或者接口名"的子类对象
 *      5.这个子类具体叫什么是不知道的,所以它是匿名内部类
 *          但是它的父类是清楚的,就是"类名或者接口名"
 *
 *      6.语法结构中的"{}"
 *      不是方法体
 *      而是匿名子类的类体
 *      既然是类体,那就在里面重写方法,新增成员等
 *
 * 通过以上语法创建了匿名的子类对象,那么如何使用该匿名子类对象呢?
 *      1.如果直接写上述语法,不用引用接收,那么它实际上就是一个匿名对象,可以直接在后面"."使用该匿名对象.
 *
 *      2.使用父类引用接收
 *          就是语法结构中的"类名或者接口名"的引用接收
 *
 * 比较上述两种使用方式
 * 1.直接使用
 *      优点:
 *          简单快捷,直接用
 *          而且可以访问匿名子类的独有成员
 *      缺点:
 *          一次性
 *
 * 2.引用接收然后使用
 *      优点:
 *          可以多次使用
 *      缺点:
 *          稍微有点麻烦
 *          不能使用匿名子类的独有成员(真的无法使用,因为不能强转)
 *
 * @since 10:00
 * @author wuguidong@cskaoyan.onaliyun.com
 */
public class Demo {
    public static void main(String[] args) {
        // 局部位置
        // 创建A类的子类对象
        new A() {
            @Override
            void test() {
                System.out.println("我是A类的匿名子类对象,我是很高级的!");
            }
        }.test();

        // 创建抽象类的子类对象
        BaseA ba = new BaseA() {
            // 匿名子类当中的独有成员
            int num = 100;

            @Override
            public void test() {
                System.out.println("我是抽象类BaseA的匿名子类对象,我很高级!");
            }
        };
        ba.test();
        // ba.num

        // 接口IA的子类对象
        new IA() {
            @Override
            public void test() {
                System.out.println("我是接口IA的子类对象!");
            }
        }.test();
    }
}

class A {
    void test() {
        System.out.println("A");
    }
}

abstract class BaseA {
    public abstract void test();
}

interface IA {
    void test();
}
